grammar Cmm;
import CmmLex;

program: stmt+;

stmt    : declStmt
        | ifStmt
        | whileStmt
        |(assignStmt SEMI)
        | writeStmt
        | stmtBlock
        | forStmt
        ;

declStmt: type deAs(COMMA deAs)* SEMI | type L_BRACKET INT R_BRACKET ID SEMI;

deAs: ID | ID ASSIGN MINUS? expr;

ifStmt: IF L_PAREN compare R_PAREN stmtBlock ( ELSE_IF L_PAREN compare R_PAREN stmtBlock)* (ELSE stmtBlock)*;

whileStmt: WHILE L_PAREN compare R_PAREN stmtBlock;

assignStmt: variable ASSIGN MINUS? expr;

writeStmt: WRITE L_PAREN expr R_PAREN SEMI;

stmtBlock: L_BRACE stmt* R_BRACE;

forStmt : FOR L_PAREN((assignStmt SEMI)|declStmt) compare SEMI assignStmt R_PAREN stmtBlock;

type: T_INT | T_DOUBLE;

variable: ID | ID L_BRACKET (expr) R_BRACKET ;

constant: INT| DOUBLE ;

compare :  UN_EQUAL compare | expr RELATION expr | L_PAREN compare R_PAREN ;

RELATION : BIGGER_THAN|LESS_THAN|NO_LESS|NO_MORE|EQUAL|UN_EQUAL;

expr    : expr1 expr2;
expr1   : expr4 expr3;
expr2   : (Plus|Minus) expr1 expr2
        |
        ;
expr3   : (Mul|Div|Mod) expr4 expr3
        |
        ;
expr4   : variable
        | constant
        | L_PAREN expr R_PAREN
        ;
